package com.gitee.chessboard.init;

import com.gitee.chessboard.annotations.DictionaryConstant;
import com.gitee.chessboard.annotations.DictionaryEnum;
import com.gitee.chessboard.manager.DictionaryManager;
import com.gitee.chessboard.parser.ConstantDictionaryParser;
import com.gitee.chessboard.parser.EnumDictionaryParser;
import com.gitee.chessboard.properties.DictionaryProperties;
import com.gitee.chessboard.scan.ScanManager;
import com.gitee.chessboard.scan.discern.AnnotationDiscernPortion;
import com.gitee.chessboard.scan.discern.DiscernHandler;
import org.springframework.beans.BeansException;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.event.SmartApplicationListener;

@DependsOn({"dictionaryManager", "enumDictionaryParser", "constantDictionaryParser", "dictionaryProperties"})
public class DictionaryManagerInit implements SmartApplicationListener, ApplicationContextAware {

    private ApplicationContext applicationContext;

    private ScanManager scanManager;
    private AnnotationDiscernPortion dictionaryConstantAnnotation;
    private AnnotationDiscernPortion dictionaryEnumAnnotation;


    public void scanManagerInit(ApplicationEnvironmentPreparedEvent event) {
        //注解识别器
        AnnotationDiscernPortion dictionaryConstantAnnotation = new AnnotationDiscernPortion();
        dictionaryConstantAnnotation.targetDescribe(DictionaryConstant.class);

        AnnotationDiscernPortion dictionaryEnumAnnotation = new AnnotationDiscernPortion();
        dictionaryEnumAnnotation.targetDescribe(DictionaryEnum.class);

        //创建扫描控制器
        ScanManager scanManager = new ScanManager();
        DiscernHandler discernHandler = scanManager.getDiscernHandler();
        discernHandler.addDiscern(dictionaryConstantAnnotation);
        discernHandler.addDiscern(dictionaryEnumAnnotation);
        scanManager.discern(event.getEnvironment().getProperty(DictionaryProperties.dictionaryScan));
        this.scanManager = scanManager;
        this.dictionaryConstantAnnotation = dictionaryConstantAnnotation;
        this.dictionaryEnumAnnotation = dictionaryEnumAnnotation;

    }

    /**
     * 初始DictionaryManager
     */
    public void dictionaryManagerInit() {
        DictionaryManager dictionaryManager = applicationContext.getBean(DictionaryManager.class);
        ConstantDictionaryParser constantDictionaryParser = applicationContext.getBean(ConstantDictionaryParser.class);
        EnumDictionaryParser enumDictionaryParser = applicationContext.getBean(EnumDictionaryParser.class);
        DictionaryProperties dictionaryProperties = applicationContext.getBean(DictionaryProperties.class);

        dictionaryManager.setConstantDictionaryParser(constantDictionaryParser);
        dictionaryManager.setEnumDictionaryParser(enumDictionaryParser);
        dictionaryManager.setEnums(dictionaryProperties.getEnumerate());
        dictionaryManager.setConstant(dictionaryProperties.getConstant());
        //将扫描到的内容添加到缓存中
        dictionaryManager.setScanManager(scanManager);
        dictionaryManager.getEnums().addAll(dictionaryEnumAnnotation.getDiscernResults());
        dictionaryManager.getConstant().addAll(dictionaryConstantAnnotation.getDiscernResults());
        dictionaryManager.init();
    }

    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType)
                || ApplicationReadyEvent.class.isAssignableFrom(eventType);
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(event.getClass())) {
            scanManagerInit((ApplicationEnvironmentPreparedEvent) event);
        }
        if (ApplicationReadyEvent.class.isAssignableFrom(event.getClass())) {
            dictionaryManagerInit();
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

}